package com.xltt.watchserver;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.google.gson.Gson;
import com.xltt.watchserver.bean.NotificationMessage;
import com.xltt.watchserver.bean.ByteUtil;
import com.xltt.watchserver.bean.User;
import com.xltt.watchserver.bean.Command;
import com.xltt.watchserver.utils.ControlPushEvent;
import com.xltt.watchserver.utils.Logger;

import java.util.Arrays;
import java.util.UUID;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class WatchService extends Service {

    private static final String TAG = "WatchService";
    //服务uuid
    public static UUID UUID_SERVER = UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb");
    //读的特征值¸
    public static UUID UUID_CHAR_READ = UUID.fromString("0000ffe3-0000-1000-8000-00805f9b34fb");
    //写的特征值
    public static UUID UUID_CHAR_WRITE = UUID.fromString("0000ffe4-0000-1000-8000-00805f9b34fb");
    public static final String FILTER_BLE_NAME = "W302";
    public static final int MSG_TOAST_CONNECT_SUCCESS = 1;
    private BluetoothManager mBluetoothManager;
    private BluetoothGattServer mBluetoothGattServer;
    private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
    private BluetoothGattService mBluetoothGattService;
    private int mMtu = 0;
    private byte[] mTempBuff;

    private void regRevice(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        context.registerReceiver(mBluethRevice, filter);
    }

    private void unRegRevice(Context context) {
        context.unregisterReceiver(mBluethRevice);
    }

    private BroadcastReceiver mBluethRevice = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
            switch (blueState) {
                case BluetoothAdapter.STATE_TURNING_ON:
                    Logger.d("蓝牙正在打开");
                    break;
                case BluetoothAdapter.STATE_ON:
                    Logger.d("蓝牙已经打开");
                    startGattService();
                    break;
                case BluetoothAdapter.STATE_TURNING_OFF:
                    Logger.d("蓝牙正在关闭");
                    stopGattService();
                    break;
                case BluetoothAdapter.STATE_OFF:
                    Logger.d("蓝牙已经关闭");
                    break;
            }
        }
    };

    /**
     * 启动ble服务
     */
    private void startGattService() {
        BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        String bleName = mBluetoothAdapter.getName();
        String imei = getImei(this);
        Logger.d("startGattService() 蓝牙名称 = " + bleName + ",imei = " + imei);
        if (imei.length() > 4) {
            String bleName2 = imei.substring(imei.length() - 4, imei.length());
            if (bleName.lastIndexOf(bleName2) == -1) {
                bleName += "_" + bleName2;
            }
        }
        startAdvertising(bleName);
        Logger.d("startGattService()开始启动Gatt服务,蓝牙名称 =" + bleName);
    }

    /**
     * 关闭ble服务
     */
    private void stopGattService() {
        if (mBluetoothLeAdvertiser != null) {
            mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
        }
        if (mBluetoothGattServer != null) {
            mBluetoothGattServer.removeService(mBluetoothGattService);
        }
        Logger.d("stopGattService()结束Gatt服务");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Logger.d("onBind()");
        return null;
    }

    @Override
    public void onCreate() {
        Logger.d("onCreate()");
        regRevice(this);
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Logger.d("onStartCommand()");
//        BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//        if(mBluetoothAdapter == null){
//            Toast.makeText(this,"bluetooth adapter is null",Toast.LENGTH_SHORT).show();
//            return super.onStartCommand(intent, flags, startId);
//        }
//        String name = mBluetoothAdapter.getName();
//        Logger.d("current blueth name = " + name);
//        startAdvertising(TextUtils.isEmpty(name) ? FILTER_BLE_NAME : name);
        startGattService();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Logger.d("onDestroy()");
        /*if(mBluetoothLeAdvertiser != null){
            mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
        }*/
        super.onDestroy();
    }

    /**
     * 创建Ble服务端
     */
    private void startAdvertising(String name) {
        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        BluetoothAdapter bluetoothAdapter = mBluetoothManager.getAdapter();
        //BLE广播设置
        AdvertiseSettings settings = new AdvertiseSettings.Builder()
                .setConnectable(true)//是否被连接
                .setTimeout(0)//超时时间
                .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)//发射功率设置为低延迟模式
                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)//广播模式
                .build();
        //广播数据设置
        AdvertiseData advertiseData = new AdvertiseData.Builder()
                .setIncludeDeviceName(true)//是否在广播中携带设备的名称
                .setIncludeTxPowerLevel(true)//是否在广播中携带信号强度
                .build();
        //扫描回应的广播设置
//        AdvertiseData scanResponseData = new AdvertiseData.Builder()
//                .setIncludeTxPowerLevel(true)  //是否在广播中携带设备的名称
//                .addServiceData(new ParcelUuid(parcelUUID), serviceData) //在scanrecord中添加的数据
//                .build();
        //设置BLE设备的名称
        bluetoothAdapter.setName(name);
        //开启服务
        mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
        mBluetoothLeAdvertiser.startAdvertising(settings,
                advertiseData,
                mAdvertiseCallback);
    }

    /**
     * Ble服务监听
     */
    private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            super.onStartSuccess(settingsInEffect);
            Logger.d("onStartSuccess() ,Gatt服务开启成功，添加读写特征值,监听客户端发送得数据");
            //Toast.makeText(getApplicationContext(), "服务开启成功", Toast.LENGTH_SHORT).show();
            addWriteAndReadService();
        }
    };

    /**
     * 添加通信服务
     */
    private void addWriteAndReadService() {
        mBluetoothGattService = new BluetoothGattService(UUID_SERVER, BluetoothGattService.SERVICE_TYPE_PRIMARY);
        //只读的特征值
        BluetoothGattCharacteristic characteristicRead = new BluetoothGattCharacteristic(UUID_CHAR_READ,
                BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
                BluetoothGattCharacteristic.PERMISSION_READ);
        //只写的特征值
        BluetoothGattCharacteristic characteristicWrite = new BluetoothGattCharacteristic(UUID_CHAR_WRITE,
                BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ
                        | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
                BluetoothGattCharacteristic.PERMISSION_WRITE | BluetoothGattCharacteristic.PERMISSION_READ);
        //将特征值添加至服务里
        mBluetoothGattService.addCharacteristic(characteristicRead);
        mBluetoothGattService.addCharacteristic(characteristicWrite);

        //监听客户端的连接
        mBluetoothGattServer = mBluetoothManager.openGattServer(this, mGattServerCallback);
        //添加服务
        mBluetoothGattServer.addService(mBluetoothGattService);
        Logger.d("addWriteAndReadService(),读写特征值服务开启成功，mGattServerCallbac开始等待客户端连接");
    }


    /**
     * 获取客户端数据
     */
    private BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
        @Override
        public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
            super.onConnectionStateChange(device, status, newState);
            String state = "";
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                state = "连接成功";
                //TODO IOS中ancs服务数据
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                state = "连接断开";
            }
            Logger.d("收到设备 = " + device.toString() + " 连接，状态 = " + state);
        }

        @Override
        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
            super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
            Logger.d("收到客户端发送得数据");
            //1、告诉客户端接收到数据
            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
            //2、解析数据
            parseData(value);
        }

        @Override
        public void onMtuChanged(BluetoothDevice device, int mtu) {
            super.onMtuChanged(device, mtu);
            mMtu = mtu;
            Logger.d("收到设备 = " + device.getName() + " 连接成功，协商mtu值 = " + mtu);
//            Message msg = new Message();
//            msg.what = MSG_TOAST_CONNECT_SUCCESS;
//            handler.removeMessages(msg.what);
//            handler.sendMessage(msg);
            //Looper.prepare();
            //Toast.makeText(getApplicationContext(), "连接成功", Toast.LENGTH_SHORT).show();
            //Looper.loop();
        }
    };

//    private Handler handler = new Handler() {
//        @Override
//        public void handleMessage(@NonNull Message msg) {
//            super.handleMessage(msg);
//            Toast.makeText(getApplicationContext(), "与通信apk连接成功", Toast.LENGTH_SHORT).show();
//        }
//    };

    /**
     * 解析客户端数据
     *
     * @param data
     */
    private void parseData(byte[] data) {
        String str = new String(data);
        Logger.d("收到了客户端发过来的byte数据 = " + str + ",长度 = " + data.length);
        String strData = Arrays.toString(ByteUtil.getHexStrings(data));
        Logger.d("字节数据 = " + strData);
        if (data.length > mMtu) {
            mTempBuff = data;
            Logger.d("客户端数据字节长度大于协商mtu长度，需要进行分包接收");
            return;
        }
        //data = ByteUtil.addBytes(data, mTempBuff);

        if (data[0] != (byte) 0xAB) {
            Logger.d("客户端数据发送错误！");
            return;
        }

        if (!ByteUtil.isSum(data)) {
            Logger.d("客户端数据校验失败！");
            return;
        }

        Logger.d("字节命令数据 data[3] = " + data[3] + ", data[5]: " + data[5]);
        switch (data[3]) {
            case Command.COMMAND_BIND:
                String json = new String(ByteUtil.getData(data));
                final User user = new Gson().fromJson(json, User.class);
                Logger.d("user = " + user.toString());
                //Toast.makeText(getApplicationContext(), user.toString(), Toast.LENGTH_SHORT).show();

                new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                    @Override
                    public void run() {
//                        int result = user.getResult();
//                        if(result != 1){
//                            return;
//                        }
                        String userName = user.getUsername();
                        String password = user.getPassword();
                        if (!TextUtils.isEmpty(userName)) {
                            Settings.Global.putString(getContentResolver(), "username", userName);
                            Settings.Global.putString(getContentResolver(), "password", password);
                            Settings.Global.putInt(getContentResolver(), "watch_bind_enabled", 1);
                        }
                        //gotoLauncher();
                    }
                }, 200);
                break;
            case Command.COMMAND_NOTIFICATION:
                if (data[5] == Command.COMMAND_NOTIFICATION_MESSAGE
                        || data[5] == Command.COMMAND_NOTIFICATION_INCOMING_CALL
                        || data[5] == Command.COMMAND_NOTIFICATION_INCOMING_CALL_ACCEPT
                        || data[5] == Command.COMMAND_NOTIFICATION_INCOMING_CALL_MISSED) {
                    String json2 = new String(ByteUtil.getData(data));
                    final NotificationMessage notification = new Gson().fromJson(json2, NotificationMessage.class);
                    Logger.d("notification = " + notification.toString());
                    //Toast.makeText(getApplicationContext(), notification.toString(), Toast.LENGTH_SHORT).show();
                    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Logger.d("Bevis add to saveDataToLauncher COMMAND_NOTIFICATION_MESSAGE");
                            String packageName = notification.getPackageName();
                            String title = notification.getTitle();
                            String content = notification.getContent();
                            saveDataToLauncher(packageName, title, content);
                        }
                    }, 200);
                } else if (data[5] == Command.COMMAND_NOTIFICATION_INCOMING_CALL_REJECT) {
                    Logger.d("COMMAND_NOTIFICATION_INCOMING_CALL_REJECT");
                    String json2 = new String(ByteUtil.getData(data));
                    final NotificationMessage notification = new Gson().fromJson(json2, NotificationMessage.class);
                    Logger.d("notification = " + notification.toString());
                    //Toast.makeText(getApplicationContext(), notification.toString(), Toast.LENGTH_SHORT).show();
                    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Logger.d("Bevis add to saveDataToLauncher COMMAND_NOTIFICATION_MESSAGE");
                            String packageName = notification.getPackageName();
                            String title = notification.getTitle();
                            String content = "拒接来电";//notification.getContent();
                            saveDataToLauncher(packageName, title, content);
                        }
                    }, 200);
                } else if (data[5] == Command.COMMAND_NOTIFICATION_INCOMING_CALL_HANGUP) {
                    Logger.d("COMMAND_NOTIFICATION_INCOMING_CALL_HANGUP");
                    String json2 = new String(ByteUtil.getData(data));
                    final NotificationMessage notification = new Gson().fromJson(json2, NotificationMessage.class);
                    Logger.d("notification = " + notification.toString());
                    //Toast.makeText(getApplicationContext(), notification.toString(), Toast.LENGTH_SHORT).show();
                    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Logger.d("Bevis add to saveDataToLauncher COMMAND_NOTIFICATION_MESSAGE");
                            String packageName = notification.getPackageName();
                            String title = notification.getTitle();
                            String content = "通话结束";//notification.getContent();
                            saveDataToLauncher(packageName, title, content);
                        }
                    }, 200);
                }
                break;
        }
    }

    /**
     * 通知数据
     *
     * @param packageName
     * @param title
     * @param content
     */
    private void saveDataToLauncher(String packageName, String title, String content) {
        ControlPushEvent pushEvent = new ControlPushEvent();
        pushEvent.setServiceId(packageName);
        pushEvent.setContent(content);
        pushEvent.setResult(1);
        pushEvent.setOperationTime(System.currentTimeMillis());
        String data = new Gson().toJson(pushEvent);
        Settings.Global.putString(getContentResolver(), "vehicle_cmd_list", data);
        Logger.d("Bevis add to saveDataToLauncher data: " + data);
    }

    /**
     * esim激活
     */
    private void gotoLauncher() {
        Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.xltt.launcher");
        startActivity(LaunchIntent);
        Logger.d("gotoLauncher");
    }

    /**
     * 获取设备imei号
     *
     * @return
     */
    private String getImei(Context context) {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
        String imei = "";
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            imei = telephonyManager.getImei();
        } else {
            imei = telephonyManager.getDeviceId();
        }
        return imei;
    }

}